package com.zz.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zz.common.Log;
import com.zz.common.R;
import com.zz.dto.BoxDto;
import com.zz.entity.Box;
import com.zz.entity.Club;
import com.zz.entity.ESBox;
import com.zz.service.BoxService;
import com.zz.service.ClubService;
import com.zz.service.ESBoxService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 周紫
 */
@RestController
@RequestMapping("/box")
@Slf4j
@CrossOrigin
@Validated
public class BoxController {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;

    @Autowired
    private BoxService boxService;

    @Autowired
    private ClubService clubService;

    @Autowired
    private ESBoxService esBoxService;


    /**
     *
     * @param boxDto
     * @return
     * 新增投稿
     * 接口测试成功
     * 周紫
     */
    @PostMapping("/add")
    @CacheEvict(cacheNames = "boxCache#3600",allEntries = true)
    @Log(title = "用户新增投稿",dataLocationType = "body")
    public R<String> saveBox(@RequestBody @Valid BoxDto boxDto){

        String clubName = boxDto.getClubName();
        // 条件构造器
        LambdaQueryWrapper<Club> queryWrapper = new LambdaQueryWrapper<>();
        // 添加过滤条件
        queryWrapper.like(Club::getName, clubName);

        Club club = clubService.getOne(queryWrapper);

        Box box = new Box();
        // 对象拷贝
        BeanUtils.copyProperties(boxDto, box, "clubName");
        box.setClubId(club.getId());

        boxService.save(box);
        return R.success("新增投稿成功！");
    }


    /**
     * 活动投稿箱分页展示
     * 周紫
     * @param page
     * @param pageSize
     * @return
     */
    @GetMapping("/page")
    @RequiresRoles("leader")
    @Cacheable(cacheNames="boxCache#3600",key = "'box'+#page+#pageSize+#theme+#request",sync = true)
    @Log(title = "分页展示活动投稿箱",dataLocationType = "link")
    public R<Page> pageBox(@RequestParam @NotNull(message = "起始页码不能为空") int page,
                        @RequestParam @NotNull(message = "每页最大数不能为空")int pageSize,
                        @Nullable @RequestParam String theme, HttpServletRequest request) {
        return boxService.page(page, pageSize, theme, request);
    }



    @GetMapping("/getHightByTheme")
    public R<List<ESBox>> getHightByTheme(String value){

        //根据一个值查询多个字段  并高亮显示  这里的查询是取并集，即多个字段只需要有一个字段满足即可
        //需要查询的字段
        BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("theme",value));

        //构建高亮查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withHighlightFields(new HighlightBuilder.Field("theme"))
                .withHighlightBuilder(new HighlightBuilder().preTags("<span style='color:red'>").postTags("</span>"))
                .build();
        //查询
        SearchHits<ESBox> search = elasticsearchTemplate.search(searchQuery, ESBox.class);
        //得到查询返回的内容
        List<SearchHit<ESBox>> searchHits = search.getSearchHits();
        //设置一个最后需要返回的实体类集合
        List<ESBox> boxes = new ArrayList<>();
        //遍历返回的内容进行处理
        for(SearchHit<ESBox> searchHit:searchHits){
            //高亮的内容
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            //将高亮的内容填充到content中
            searchHit.getContent().setTheme(highlightFields.get("theme")==null ? searchHit.getContent().getTheme():highlightFields.get("theme").get(0));
            //放到实体类中
            boxes.add(searchHit.getContent());
        }
        return R.success(boxes);
    }


    //---------------------------------ES----------------------------------------------
    @PostMapping("/esAdd")
    public Map<String, String> esAdd(String code) {
        elasticsearchTemplate.putMapping(ESBox.class);
        esBoxService.addToES(code);
        Map<String, String> map = new HashMap<>();
        map.put("msg", "esAdd ok");
        return map;
    }
    @PostMapping("/esUpdate")
    public Map<String, String> esUpdate(@RequestBody ESBox esBox) {
        String msg = esBoxService.esUpdate(esBox);
        Map<String, String> map = new HashMap<>();
        map.put("msg", "esUpdate "+msg);
        return map;
    }
    @PostMapping("/esDelete")
    public Map<String, String> esDelete(@RequestBody ESBox esBox) {
        esBoxService.esDelete(esBox);
        Map<String, String> map = new HashMap<>();
        map.put("msg", "esDelete ok");
        return map;
    }

}
